<template>
  <div class="markdown-modal" v-if="visible" @click.self="closeModal">
    <div class="modal-content">
      <div class="modal-header">
        <h3>{{ title || '文档预览' }}</h3>
        <button @click="closeModal" class="close-btn">&times;</button>
      </div>
      <div class="modal-body">
        <div v-if="loading" class="loading">
          <div class="spinner"></div>
          <p>加载中...</p>
        </div>
        <div v-else-if="error" class="error">
          <p>{{ error }}</p>
          <button @click="loadContent" class="retry-btn">重新加载</button>
        </div>
        <div v-else class="content-wrapper">
          <!-- 目录侧边栏 -->
          <div class="toc-sidebar" v-if="tableOfContents.length > 0">
            <h4>目录</h4>
            <nav class="toc-nav">
              <div v-for="(heading, index) in tableOfContents" :key="index"
                   class="toc-item"
                   :class="{
                     'level-1': heading.level === 1,
                     'level-2': heading.level === 2,
                     'level-3': heading.level === 3,
                     'level-4': heading.level >= 4,
                     'active': activeHeading === heading.id
                   }"
                   @click="scrollToHeading(heading.id)">
                {{ heading.text }}
              </div>
            </nav>
          </div>
          
          <!-- 内容区域 -->
          <div class="markdown-content" 
               ref="contentRef"
               @scroll="handleScroll"
               v-html="content"></div>
        </div>
      </div>
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, watch, nextTick } from 'vue'
import { marked } from 'marked'

interface Props {
  visible: boolean
  filePath?: string
  title?: string
  fileType?: string
}

interface Emits {
  (e: 'close'): void
}

interface TocItem {
  id: string
  text: string
  level: number
}

const props = defineProps<Props>()
const emit = defineEmits<Emits>()

const loading = ref(false)
const error = ref('')
const content = ref('')
const contentRef = ref<HTMLElement | null>(null)
const tableOfContents = ref<TocItem[]>([])
const activeHeading = ref('')

const closeModal = () => {
  emit('close')
  // 清理状态
  content.value = ''
  error.value = ''
  tableOfContents.value = []
  activeHeading.value = ''
}

const generateTableOfContents = (htmlContent: string) => {
  const parser = new DOMParser()
  const doc = parser.parseFromString(htmlContent, 'text/html')
  const headings = doc.querySelectorAll('h1, h2, h3, h4, h5, h6')

  const toc: TocItem[] = []

  headings.forEach((heading, index) => {
    const level = parseInt(heading.tagName.charAt(1))
    const text = heading.textContent || ''
    const id = `heading-${index}`
    
    // 为标题添加ID
    heading.id = id
    
    toc.push({ id, text, level })
  })

  tableOfContents.value = toc
  return doc.body.innerHTML
}

const scrollToHeading = (headingId: string) => {
  if (contentRef.value) {
    const element = contentRef.value.querySelector(`#${headingId}`)
    if (element) {
      element.scrollIntoView({ behavior: 'smooth', block: 'start' })
    }
  }
}

const handleScroll = () => {
  if (!contentRef.value) return
  
  const headings = contentRef.value.querySelectorAll('h1, h2, h3, h4, h5, h6')
  const scrollTop = contentRef.value.scrollTop
  
  let currentHeading = ''
  
  headings.forEach((heading) => {
    const rect = heading.getBoundingClientRect()
    const containerRect = contentRef.value!.getBoundingClientRect()
    
    if (rect.top - containerRect.top <= 100) {
      currentHeading = heading.id
    }
  })
  
  activeHeading.value = currentHeading
}

const loadContent = async () => {
  if (!props.filePath) return
  
  loading.value = true
  error.value = ''
  content.value = ''
  
  try {
    if (props.fileType === 'md') {
      const response = await fetch(props.filePath)
      if (!response.ok) {
        throw new Error('无法加载文件内容')
      }
      
      const markdownText = await response.text()
      
      // 配置marked选项
      marked.setOptions({
        breaks: true,
        gfm: true,
        headerIds: false,
        mangle: false
      })
      
      // 使用marked渲染Markdown
      const htmlContent = await marked(markdownText)
      
      // 生成目录并更新内容
      const contentWithIds = generateTableOfContents(htmlContent)
      content.value = contentWithIds
      
      // 等待DOM更新后滚动到顶部
      await nextTick()
      if (contentRef.value) {
        contentRef.value.scrollTop = 0
      }
    } else {
      // 对于非Markdown文件，显示提示信息
      content.value = `<p>此文件类型（${props.fileType}）暂不支持预览。</p>`
      tableOfContents.value = []
    }
  } catch (err) {
    console.error('预览文件失败:', err)
    error.value = err instanceof Error ? err.message : '预览文件时发生错误'
  } finally {
    loading.value = false
  }
}

// 监听文件路径变化，自动加载内容
watch(() => [props.visible, props.filePath, props.fileType], ([visible, filePath, fileType]) => {
  if (visible && filePath) {
    loadContent()
  }
}, { immediate: true })
</script>

<style scoped>
.markdown-modal {
  position: fixed;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: rgba(0, 0, 0, 0.5);
  display: flex;
  justify-content: center;
  align-items: center;
  z-index: 1000;
}

.modal-content {
  background: white;
  border-radius: 8px;
  width: 95%;
  max-width: 1200px;
  height: 90%;
  display: flex;
  flex-direction: column;
  box-shadow: 0 4px 20px rgba(0, 0, 0, 0.15);
}

.modal-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 1rem 1.5rem;
  border-bottom: 1px solid #e5e7eb;
  background-color: #f9fafb;
  border-radius: 8px 8px 0 0;
  flex-shrink: 0;
}

.modal-header h3 {
  margin: 0;
  font-size: 1.25rem;
  font-weight: 600;
  color: #374151;
}

.close-btn {
  background: none;
  border: none;
  font-size: 1.5rem;
  cursor: pointer;
  color: #6b7280;
  padding: 0;
  width: 30px;
  height: 30px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  transition: all 0.2s;
}

.close-btn:hover {
  background-color: #f3f4f6;
  color: #374151;
}

.modal-body {
  flex: 1;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  color: #6b7280;
}

.spinner {
  width: 40px;
  height: 40px;
  border: 4px solid #f3f4f6;
  border-top: 4px solid #3b82f6;
  border-radius: 50%;
  animation: spin 1s linear infinite;
  margin-bottom: 1rem;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.error {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  flex: 1;
  color: #dc2626;
  text-align: center;
}

.retry-btn {
  margin-top: 1rem;
  padding: 0.5rem 1rem;
  background-color: #3b82f6;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  transition: background-color 0.2s;
}

.retry-btn:hover {
  background-color: #2563eb;
}

.content-wrapper {
  display: flex;
  flex: 1;
  overflow: hidden;
}

.toc-sidebar {
  width: 250px;
  background-color: #f8fafc;
  border-right: 1px solid #e2e8f0;
  overflow-y: auto;
  flex-shrink: 0;
}

.toc-sidebar h4 {
  margin: 0;
  padding: 1rem;
  font-size: 1rem;
  font-weight: 600;
  color: #374151;
  border-bottom: 1px solid #e2e8f0;
  background-color: #f1f5f9;
}

.toc-nav {
  padding: 0.5rem 0;
}

.toc-item {
  padding: 0.5rem 1rem;
  cursor: pointer;
  font-size: 0.875rem;
  color: #4b5563;
  border-left: 3px solid transparent;
  transition: all 0.2s;
}

.toc-item:hover {
  background-color: #e2e8f0;
  color: #1f2937;
}

.toc-item.active {
  background-color: #dbeafe;
  color: #1d4ed8;
  border-left-color: #3b82f6;
  font-weight: 500;
}

.toc-item.level-1 {
  font-weight: 600;
}

.toc-item.level-2 {
  padding-left: 1.5rem;
}

.toc-item.level-3 {
  padding-left: 2rem;
  font-size: 0.8rem;
}

.toc-item.level-4 {
  padding-left: 2.5rem;
  font-size: 0.75rem;
  color: #6b7280;
}

.markdown-content {
  flex: 1;
  overflow-y: auto;
  padding: 1.5rem;
  line-height: 1.6;
  color: #374151;
}

/* Markdown 样式 */
.markdown-content :deep(h1),
.markdown-content :deep(h2),
.markdown-content :deep(h3),
.markdown-content :deep(h4),
.markdown-content :deep(h5),
.markdown-content :deep(h6) {
  margin-top: 1.5rem;
  margin-bottom: 0.5rem;
  font-weight: 600;
  color: #1f2937;
  scroll-margin-top: 1rem;
}

.markdown-content :deep(h1) {
  font-size: 1.875rem;
  border-bottom: 2px solid #e5e7eb;
  padding-bottom: 0.5rem;
}

.markdown-content :deep(h2) {
  font-size: 1.5rem;
  border-bottom: 1px solid #e5e7eb;
  padding-bottom: 0.25rem;
}

.markdown-content :deep(h3) {
  font-size: 1.25rem;
}

.markdown-content :deep(h4) {
  font-size: 1.125rem;
}

.markdown-content :deep(p) {
  margin-bottom: 1rem;
}

.markdown-content :deep(ul),
.markdown-content :deep(ol) {
  margin-bottom: 1rem;
  padding-left: 1.5rem;
}

.markdown-content :deep(li) {
  margin-bottom: 0.25rem;
}

.markdown-content :deep(pre) {
  background-color: #f8fafc;
  border: 1px solid #e2e8f0;
  border-radius: 6px;
  padding: 1rem;
  overflow-x: auto;
  margin-bottom: 1rem;
}

.markdown-content :deep(code) {
  background-color: #f1f5f9;
  padding: 0.125rem 0.25rem;
  border-radius: 3px;
  font-size: 0.875rem;
  font-family: 'Courier New', Courier, monospace;
}

.markdown-content :deep(pre code) {
  background-color: transparent;
  padding: 0;
}

.markdown-content :deep(blockquote) {
  border-left: 4px solid #e5e7eb;
  padding-left: 1rem;
  margin: 1rem 0;
  color: #6b7280;
  font-style: italic;
}

.markdown-content :deep(table) {
  width: 100%;
  border-collapse: collapse;
  margin-bottom: 1rem;
}

.markdown-content :deep(th),
.markdown-content :deep(td) {
  border: 1px solid #e5e7eb;
  padding: 0.5rem;
  text-align: left;
}

.markdown-content :deep(th) {
  background-color: #f9fafb;
  font-weight: 600;
}

.markdown-content :deep(img) {
  max-width: 100%;
  height: auto;
  border-radius: 4px;
  margin: 1rem 0;
}

.markdown-content :deep(a) {
  color: #3b82f6;
  text-decoration: underline;
}

.markdown-content :deep(a:hover) {
  color: #1d4ed8;
}

/* 移动端适配 */
@media (max-width: 768px) {
  .modal-content {
    width: 98%;
    height: 95%;
  }
  
  .content-wrapper {
    flex-direction: column;
  }
  
  .toc-sidebar {
    width: 100%;
    max-height: 200px;
    border-right: none;
    border-bottom: 1px solid #e2e8f0;
  }
  
  .markdown-content {
    padding: 1rem;
    font-size: 0.875rem;
  }
}
</style>